﻿using System;
using System.Collections.Generic;
using System.Deployment.Application;
using System.Linq;
using System.Windows.Forms;

using QuickTuner.Properties;
using QuickTuner.RadioProtocol;
using QuickTuner.Util;

namespace QuickTuner
{
    internal static partial class Program
    {
        internal static Settings Config;

        internal static Radio TheRadio;
        internal static radioForm MainForm;

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        private static void Main()
        {
            // to generate BIN file from an XML file in embedded resource
            // uncomment the following block
            //var ms = new System.IO.MemoryStream(
            //    System.Text.Encoding.Default.GetBytes(Resources.radio_xml));
            //var r = Radio.LoadFrom(ms);
            //var fs = System.IO.File.OpenWrite(@"C:\temp\radio.bin");
            //r.SaveBinaryTo(fs);
            //fs.Flush();
            //fs.Close();
            //fs.Dispose();
            //ms.Close();
            //ms.Dispose();
            //return;

            // for resetting in dev environment, execute:
            //Storage.LoadDefaultTemplates();

            // visual themes support, required to run first thing
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

#if PROFILING
            // Do nothing, i.e. don't access IsolatedStorage
            // so QuickTuner.exe can be loaded in a profiling application

#elif DEBUG
            // always run configure radio protocol when debugging
            configureRadioProtocol();

#else
            // if first-time, call the setup routine
            if (ApplicationDeployment.IsNetworkDeployed)
                if (ApplicationDeployment.CurrentDeployment.IsFirstRun)
                    firstRun();

#endif


            // on first instance, call createMainForm to create the main form and run it
            var controller = new InstanceController(createMainForm, true);

            // on second instance, assume a radio:// protocol has been passed
            // thus invoking the processCommandLine method instead
            controller.StartupNextInstance += (sender, e) => processCommandLine(e.CommandLine);

            // cleanup 
            controller.Shutdown += (sender, e) => shutdown();

            // spin the main loop
            controller.Run(Environment.GetCommandLineArgs());
        }


        /// <summary>
        /// Creates the main QuickTuner form and related supports.
        /// </summary>
        public static Form createMainForm()
        {
            // load the saved settings, not the default values
            Config = Settings.Default;

            
#if PROFILING
            // don't access IsolatedStorage if profiling
            var radio = new Radio();

#else
            // load radio from storage
            var radio = Storage.LoadRadio();

#endif


            radio.PlayEngine = new IEPlayEngine();

            TheRadio = radio;

            // create main form
            MainForm = new radioForm(radio);

            return MainForm;
        }

        /// <summary>
        /// Process command line passed from a new instance.
        /// Which is the case when the radio:// protocol was activated.
        /// </summary>
        private static void processCommandLine(IEnumerable<string> cmdLineArgs)
        {
            var radio = TheRadio;
            var form = MainForm;

            // skip the first arg, which is the exe path
            cmdLineArgs = cmdLineArgs.Skip(1);

            // does nothing if no radio instance exists
            if (radio == null) return;

            // parse the actions passed in
            var parser = new ProtocolParser();
            var actions = cmdLineArgs.Select(arg => parser.Parse(arg));

            // filter out and execute all executable action
            actions = actions.Where(act => act.CanExecute(radio));
            actions.ForEach(act => act.Execute(radio));

            // reflect changes on main form
            form.RefreshRadioState();
        }

        /// <summary>
        /// Save setings and cleanup resources
        /// </summary>
        public static void shutdown()
        {
            if (TheRadio == null) return;

#if !PROFILING //don't access IsolatedStorage if in profiling mode
            Storage.SaveRadio(TheRadio);
#endif
            Config.Save();
        }
    }
}